home *** CD-ROM | disk | FTP | other *** search
- /* TwistDownList.h */
- /*
- * List In A List Sample
- * TwistDownList.h
- * Copyright © 1993-94 Apple Computer Inc. All rights reserved.
- * Edit History
- * 94.01.03 MM Original release for the develop article.
- * 94.10.16 MM Use pascal calling conventions (reader suggestion). Reserved flag
- * bits for application programs; added a sort function; changed the
- * user-specified drawing function so that the TwistDownRecord is
- * passed (as a pointer to a locked handle) so that the drawing
- * function can access the flag bits. Added horizontal scrollbar
- * support. Added "sibling-set" functions to simplify normal list
- * operation. Updated to Universal Headers (ETO 15).
- * 94.11.26 MM Updated for headers "Universal Interfaces 2.0a3c1" -- these
- * are incompatible with ETO 15.
- *
- * Note that "list" is ambiguous, referring either to a List Manager list or to
- * a "Lisp-like" list. In the following documentation, "cell" will always refer
- * to a List Manager list cell, while "element" will always refer to a Lisp
- * cell. Note that elements are not always displayed by the List Manager.
- */
- #ifndef _TwistDownList_
- #define _TwistDownList_
-
- #ifndef REZ
- #include "ConditionalMacros.h"
- #include "Types.h"
- #include "MixedMode.h"
- #include "OSUtils.h"
- #include "Files.h"
- #include "QuickdrawText.h"
- #include "QuickDraw.h"
- #include "Events.h"
- #include "Errors.h"
- #include "Memory.h"
- #include "Menus.h"
- #include "Controls.h"
- #include "Windows.h"
- #include "TextEdit.h"
- #include "Dialogs.h"
- #include "MachineExceptions.h"
- #if 1 /* This is for PCI development only */
- #include "Kernel.h"
- #include "NameRegistry.h"
- #include "CodeFragments.h"
- #endif
- #include "Devices.h"
- #include "Fonts.h"
- #include "Resources.h"
- #include "LowMem.h"
- #include "Lists.h"
- #include "IntlResources.h"
- #include "Script.h"
- #include "TextUtils.h"
- #include "SegLoad.h"
- #include "FixMath.h"
- #include "ToolUtils.h"
- #include "Printing.h"
-
- #ifndef TRUE
- #define TRUE 1
- #define FALSE 0
- #endif
- #ifndef NULL
- #define NULL 0
- #endif
- /*
- * This is the resource ID of the callback stub that must be defined in the
- * application's resource fork. See the example in ListInAList.r.
- */
- #define LDEF_Stub 1024
- /*
- * TwistDownClickState is the value returned by DoTwistDownClick.
- */
- typedef enum {
- kTwistDownNotInList = 0, /* The click was not in this list */
- kTwistDownNoClick, /* User changed mind */
- kTwistDownButtonClick, /* Clicked on twist-down button */
- kTwistDownClick, /* Single-click on list datum */
- kTwistDownDoubleClick /* Double-click on list datum */
- } TwistDownClickState;
-
- /*
- * This is the information needed to manage the twist-down display list. It is,
- * essentially, a classical Lisp list with recursively-defined sublists. Each
- * element contains enough information to display one component. This list is
- * stored in a handle stored in the list's private data handle. The ListManager
- * list cells contain TwistDownHdl pointers to the visible elements.
- * A value of NULL in nextElement indicates the end of a list or sublist.
- * A value of NULL in subElement means that there are no sub-elements (this
- * is a leaf). Note that the Macintosh memory manager handles garbage collection.
- *
- * The flag bits have the following meanings:
- * kHasTwistDown This list element is a sub-list (it may be empty).
- * Draw the twist-down button (even if subElement is NULL).
- * kShowSubList This list element is has a sub-list and the user wants
- * to see the contents of the sub-list, too.
- * kOldShowSubList This would be used to save the state of the kShowSubList
- * flag if it needs to be changed temporarily (to show
- * the entire hierarchy, for example).
- * The following flags are only needed by the mouse-click handler.
- * kDrawButtonFilled This is used by the mouse-click handler to signal
- * "mouse-down in button." The LDEF fills the button area.
- * kOnlyRedrawButton This is used by the mouse-click handler to signal the
- * LDEF to draw only the button, but not the list content.
- * kDrawIntermediate The user is expanding/collapsing the folder. Draw
- * the animation triangle.
- * kSelectedElement This element was selected in the display list. This is
- * a temporary value needed when the list is expanded or
- * contracted.
- * kEraseButtonArea If we are only hiliting the button (while the user has
- * pressed the mouse in the button area), we don't need to
- * erase the button before redrawing it. When the user clicks
- * -- releases the mouse in the button -- the button shape
- * will change, so the old shape must be erased. This is
- * controlled by this flag.
- * kUserFlagMask These flags may be used by the calling program.
- */
- #define kHasTwistDown 0x0001 /* This element has a sub-list */
- #define kShowSublist 0x0002 /* Display the sub-list content */
- #define kOldShowSublist 0x0004 /* Save kShowSublist state */
- #define kSelectedElement 0x0008 /* Copy "selected" from List */
- #define kDrawButtonFilled 0x0010 /* Signal "mouseDown" in button */
- #define kOnlyRedrawButton 0x0020 /* Signal "tracking mouse" */
- #define kDrawIntermediate 0x0040 /* Draw the animation polygon */
- #define kEraseButtonArea 0x0080 /* Need complete button redraw */
- #define kUserFlagMask 0xFF00 /* Reserved for caller's use */
- #define kFirstUserFlag 0x0100 /* User flags start here */
- #define kUserFlagShift 8 /* Shift to first user flag bit */
-
- struct TwistDownRecord {
- struct TwistDownRecord **nextElement; /* CDR - next on this "level" */
- struct TwistDownRecord **subElement; /* CAR - first in a sublist */
- short indentLevel; /* Indentation depth */
- unsigned short flag; /* TwistDownFlags */
- unsigned short dataLength; /* Length of actual datum */
- unsigned char data[1]; /* Datum to display */
- };
- typedef struct TwistDownRecord TwistDownRecord, *TwistDownPtr, **TwistDownHdl;
-
- /*
- * TwistDownSiblingSet simplifies creation of a linked list of TwistDown elements.
- * Usage:
- * NewTwistDownSiblingSet(&mySiblingSet);
- * status = MakeTwistDownSibling(&mySiblingSet, ...);
- * currentElement = mySiblingSet.thisElement;
- * (**currentElement).subElement = EnumerateChildOfCurrentElement(...);
- * return (mySiblingSet.firstElement);
- */
- struct TwistDownSiblingSet {
- TwistDownHdl thisElement; /* This was just created */
- TwistDownHdl firstElement; /* First in this sequence */
- TwistDownHdl previousElement; /* Previous element linkage */
- };
- typedef struct TwistDownSiblingSet TwistDownSiblingSet, *TwistDownSiblingSetPtr;
-
- /*
- * This is the function that is called to draw the user-specified list cell
- * contents. The port and font have been properly initialized and the viewRect
- * takes indentation into consideration. If this parameter is specified as NULL,
- * DrawText will be used. Note that the application can use the list's refCon to
- * pass other data to the drawing procedure.
- *
- * This function will be called to draw list cells on the display and, if the
- * default print page procedure is provided, to print list element information.
- *
- * Note: this is an incompatible change from the original release of the TwistDown
- * library that makes it possible for the drawing procedure to access the user-
- * controlled flag bits and (though it should not be necessary) the indent level.
- */
- typedef pascal void (*TwistDownDrawProc)(
- ListHandle twistDownListHdl, /* The list itself */
- TwistDownPtr twistDownPtr, /* Locked data handle */
- const Rect *viewRect /* Draw in this area */
- );
-
- /*
- * Create a twist-down list. Before calling, you must set the port to the current
- * window and specify the font and font size that is to be used to draw the list.
- * NewTwistDownList creates an empty one-column list with a vertical scroll bar
- * and no grow box. Only one item may be selected at a time; but this could
- * be changed by the application without difficulty.
- *
- * Note: unlike LNew, you should specify a correct viewRect: the scroll bars and
- * frame will be created inside the view rect.
- *
- * The TwistDownDrawProc will be called to draw a selection. If specified as
- * NULL, DrawText will be called.
- *
- * The tabIndent parameter should be set to the amount to indent successive levels
- * (zero means no indentation). Setting it to the widMax value from the current
- * font seems reasonable.
- *
- * canHiliteSelection should be TRUE for normal selection (the selection is
- * hilited). It should be FALSE if you want to supress selection. Because
- * hirearchical lists often "select" by revealing a sub-topic, this may be
- * more reasonable in many cases.
- *
- * isLeftJustify should be set TRUE for systems using the Roman alphabet. It would
- * be set FALSE for right-to-left languages such as Arabic and Hebrew. It is used
- * to configure the direction of the buttons and the location of text within
- * the displayed list cell.
- */
- pascal ListHandle NewTwistDownList(
- const Rect *viewRect,
- TwistDownDrawProc drawProc,
- unsigned short tabIndent,
- Boolean canHiliteSelection,
- Boolean isLeftJustify,
- Boolean hasGrowBox
- );
- /*
- * Dispose of a Twist Down List and its private storage. The application program
- * must itself dispose of the list data. theList may be NULL.
- */
- pascal void DisposeTwistDownList(
- ListHandle theList
- );
-
- /*
- * Move the list within the window.
- */
- pascal void MoveTwistDownList(
- ListHandle theList,
- short leftEdge,
- short topEdge
- );
- /*
- * Resize the list. The width and height parameters do not include the horizontal
- * and vertical scrollbars.
- */
- pascal void SizeTwistDownList(
- ListHandle theList,
- short newWidth,
- short newHeight
- );
- /*
- * CreateTwistDownButtons is called, internally, when the list is created.
- * if the application program changes the list cell height (by calling LSize),
- * or changes the direction of text it must re-call CreateTwistDownButtons
- * to re-create the twist-down buttons.
- */
- pascal void CreateTwistDownButtons(
- ListHandle theList
- );
- /*
- * DoTwistDownClick handles all processing after a click in the list window.
- * It returns an indication of the user action:
- * kTwistDownNotInList
- * The click was not in this list. Your application may ignore this click or
- * take other appropriate action.
- * kTwistDownNoClick
- * The user released the mouse outside of the list area: this click should be
- * ignored.
- * kTwistDownButtonClick
- * The user clicked on the twist-down button. Expand or contract the list as
- * appropriate.
- * kTwistDownClick
- * The user clicked (once) on a list datum. The application should treat this
- * as an item selection (or, it may be a click in the scroll bar). This is
- * the result of a FALSE return from LClick.
- * kTwistDownDoubleClick
- * The user double-clicked on a list datum. The application should open this
- * item or take other appropriate action. This is the result of a TRUE
- * return from LClick.
- *
- * If DoTwistDownClick returns kTwistDownButtonClick, kTwistDownClick, or
- * kTwistDownDoubleClick, selectedListCell will be set to the cell that the user
- * clicked on.
- */
- pascal TwistDownClickState DoTwistDownClick(
- ListHandle theList,
- const EventRecord *eventRecordPtr,
- Cell *selectedListCell
- );
- /*
- * ExpandOrCollapseTwistdownSubList is called when the user clicks on the
- * twist-down button. index and selectedListCell are the values returned by
- * DoTwistDownClick.
- */
- pascal void ExpandOrCollapseTwistDownList(
- ListHandle theList,
- Cell selectedListCell
- );
- /*
- * SetTwistDownListFont changes the font and font size. It then calls
- * CreateTwistDownButtons to change the twist down button dimensions.
- * SetTwistDownListFont will cause the list to be redrawn, but it does not
- * examine or modify the TwistDown list elements.
- */
- pascal void SetTwistDownListFont(
- ListHandle theList,
- short fontNumber,
- short fontSize
- );
- /*
- * Explicitly update a list without waiting for an update event. This would
- * normally only be called after an Alert or Modal Dialog terminates.
- */
- pascal void UpdateTwistDownList(
- ListHandle theList
- );
-
- /*
- * CreateVisibleList is called when the list is created. It stores the list
- * head into cell [0, 0] and calls BuildVisibleList to instantiate the display.
- */
- pascal void CreateVisibleList(
- ListHandle theList,
- TwistDownHdl twistDownHdl
- );
- /*
- * BuildVisibleList is called when the list is created, or when the user clicks on
- * a twist-down button. selectedRow is the first row that needs to be redrawn. The
- * head of the entire list has been stored into cell [0, 0].
- */
- pascal void BuildVisibleList(
- ListHandle theList,
- short selectedRow
- );
- /*
- * GetTwistDownElementHandle returns the TwistDownHdl that is stored in a List
- * cell. It will return NULL if the cell is out of bounds.
- */
- pascal TwistDownHdl GetTwistDownElementHandle(
- ListHandle theList,
- Cell theCell
- );
- /*
- * NewTwistDownSiblingSet initializes the variables that will be used to manage
- * a linked list of TwistDown list elements. Together with MakeSibling, it simplifies
- * management of the list.
- */
- pascal void NewTwistDownSiblingSet(
- TwistDownSiblingSetPtr twistDownSiblingSetPtr
- );
- /*
- * MakeTwistDownSibling adds a new element (by calling MakeTwistDownElement) to
- * the end of the current linked list. It handles the bookkeeping needed for
- * the first element.
- */
- pascal OSErr MakeTwistDownSibling(
- TwistDownSiblingSetPtr twistDownSiblingSetPtr,
- short indentLevel,
- unsigned short dataLength,
- const Ptr dataPtr
- );
- /*
- * MakeTwistDownElement adds an element to a linked list. It is designed to create
- * elements in a hierarchical linked-list where each element may be followed by a
- * successor (on the same "level") and/or by a child list (on a lower "level").
- * The parameters are as follows:
- * previousElement
- * This has a handle to the predecessor to this element. PreviousElement
- * should be NULL if this is the first element.
- * indentLevel
- * This is the indentation-level of this list element. It is only used to tab
- * the list elements on the visual display. If you never want tabbing, set
- * tabIndent to zero when the list was created. Indents start at zero.
- * dataLength
- * This is the length of the list element datum.
- * dataPtr
- * This is a pointer to the first byte of the list element datum. If NULL,
- * a data block of the requisite size will be created, but the caller is
- * responsible for filling it in.
- * result
- * If MakeElement succeeds, result will will contain a handle to the
- * list element it created. This is needed to create a successor
- * element.
- */
- pascal OSErr MakeTwistDownElement(
- TwistDownHdl previousElement,
- short indentLevel,
- unsigned short dataLength,
- const Ptr dataPtr,
- TwistDownHdl *result
- );
-
- /*
- * Append the second list to the first. Return the first element.
- */
- pascal TwistDownHdl AppendTwistDownList(
- TwistDownHdl dstTwistDownHandle,
- TwistDownHdl srcTwistDownHdl
- );
-
- /*
- * This recursive function disposes of the argument list that has the argument
- * at its head, and of all sublists linked to this list. If userProc is non-NULL,
- * it will be called when disposing each handle. This allows the caller to
- * store handle or pointer data within a list element.
- */
- typedef pascal void (*DisposeTwistDownCallback)(
- TwistDownHdl twistDownHdl,
- void *userData
- );
-
- pascal void DisposeTwistDownHdl(
- TwistDownHdl twistDownHdl,
- DisposeTwistDownCallback userProc,
- void *userData
- );
-
- /*
- * Count the number of elements in the list (whether visible or not).
- */
- pascal unsigned long CountListElements(
- TwistDownHdl twistDownHdl
- );
-
- /*
- * Sort a TwistDown list. This sorts the current list, but does not examine any
- * sublists. The caller must provide a comparison function.
- *
- * To sort a list, call SortTwistDownList(&theList, compareFunc, refCon). The
- * sort is not recursive, and returns an error if the function cannot obtain
- * enough scratch storage ((number of elements + 1) * sizeof (Handle))
- */
- /*
- * Compare two list elements, returning -1, 0, +1 depending on whether
- * listElementA is less, equal to, or greater than listElementB.
- */
- typedef pascal short (*TwistDownSortCompareProc)(
- void *refCon,
- const TwistDownHdl listElementA,
- const TwistDownHdl listElementB
- );
- /*
- * Sort a list according to the comparison function.
- */
- pascal OSErr SortTwistDownList(
- TwistDownHdl *twistDownHdlPtr,
- TwistDownSortCompareProc twistDownSortCompareProc,
- void *refCon
- );
-
- /*
- * Print a TwistDown list. This is a print manager that calls user-provided
- * functions to handle the actual printing process. (Default procedures are
- * provided for text-only lists.) Parameters:
- * theList The ListHandle that contains this list.
- * printHandlePtr This is the address of a PrintHandle. If the
- * PrintHandle is NULL, a new handle will be
- * allocated.
- * doStyleDialog TRUE to always display the style dialog.
- * twistDownPrintSetupProc This is called once to determine the number
- * of pages in the printout. It should set
- * (**hPrint).prJob.iLstPage to the total number
- * of pages. See the default routine for details.
- * If NULL, a default routine will be used that
- * prints a simple heading (date, time, and page
- * number), then uses the list font information
- * to determine the number of pages.
- * twistDownPrintImageProc This is called for each page to draw the data.
- * If NULL, a default routine will be used that
- * works with the setup function. This will use
- * the cell display routine that was provided
- * to the list creation function.
- * twistDownPrintExitProc This is called when printing completes.
- * clientData For the caller's use.
- * The caller should call InitCursor (or whatever is appropriate) after
- * PrintTwistDownList exits -- the cursor will be set to the watchCursor.
- */
- typedef pascal OSErr (*TwistDownPrintSetupProc)(
- ListHandle theList,
- THPrint printHandle,
- void *clientData,
- StringPtr dateString
- );
- typedef pascal OSErr (*TwistDownPrintImageProc)(
- ListHandle theList,
- THPrint printHandle,
- void *clientData,
- StringPtr dateString,
- const Rect *pageRect,
- short pageNumber
- );
- typedef pascal OSErr (*TwistDownPrintExitProc) (
- ListHandle theList,
- void *clientData,
- OSErr finalStatus
- );
- pascal OSErr PrintTwistDownList(
- ListHandle theList,
- THPrint *printHandlePtr,
- Boolean doStyleDialog,
- TwistDownPrintSetupProc twistDownPrintSetupProc,
- TwistDownPrintImageProc twistDownPrintImageProc,
- TwistDownPrintExitProc twistDownPrintExitProc,
- void *clientData
- );
-
- #endif /* REZ */
- #endif /* _TwistDownList_ */
-